Философия и принципы Smalltalk
Философия языка
Что такое объект - мы помним. Мы рассматривали его с точки зрения современных концепций, как Java, но всё же принцип «всё есть объект» понять несложно. Даже самые базовые сущности в Smalltalk являются обхектами.
К примеру, 1234 будет объектом класса Integer, у которого есть метод factorial.
true и false - объекты, отвечающие на сообщения ifTrue, ifFalse.
nil (аналог null) тоже объект, единственный экземпляр класса UndefinedObject (неопределенный объект).
Классы - объекты, экземпляры метаклассов. Методы - объекты. Блоки кода - объекты, которые тоже можно передавать, хранить, вызывать. То есть, в системе нет «второсортных сущностей», и всё подчиняется единой модели.
Почему мы так акцентируем на этом? Понятнее станет, если рассмотреть другие языки.
В Java, например, не всё объект, допустим int и boolean - это примитивы. В C#, int - это структура, но не объект в полном смысле. В Python есть определенные «оптимизации», а в JavaScript примитивы не всегда ведут себя как объекты при доступе к методам. Словом, везде есть «но». Smalltalk же доводит идею до абсолюта: нет никакого разделения между данными и поведением, между типами и объектами.
Единственный способ взаимодействия - это посылка сообщений. Мы как-то изучали уже термин «вызов» функции или метода. То есть мы говорим «объект.метод()». В Smalltalk немного иначе - здесь мы посылаем сообщение в объект. Тут есть фундаментальная разница в модели вычислений - сообщение не привязано к классу, оно отправляется объекту, т.е. оно независимое. А объект же сам решает, как ответить. Если объект не понимает сообщение — он получает doesNotUnderstand:, и может динамически среагировать (например, делегировать, создать метод на лету, выбросить ошибку).
Пример - условие без операторов:
(x > 0) ifTrue: [ 'positive' ] ifFalse: [ 'negative' ]
Что здесь происходит?
- (x > 0) возвращает true или false — объект.
- Мы посылаем ему сообщение ifTrue:ifFalse:.
- true и false реализуют это сообщение по-разному.
Как видим, какого-то ветвления в синтаксисе нет, есть лишь поведение объектов.
В Smalltalk нет аннотаций типов. Никаких String name, List<int>. Тип является свойством объекта, а не переменной:
| x |
x := 42.
x := 'hello'.
x := [ 1 + 2 ].
Но ошибки обнаруживаются только во время выполнения, и сложно порой понять, что ожидает метод, и как следствие - труднее оптимизировать. В других языках мы пишем код в редакторе, сохраняем в файл, запускаем компилятор, запускаем программу, при ошибках читаем логи, исправляем, перезапускаем.
В ST же мы погружаемся в работающую систему, где код - это объекты в памяти, и изменяя класс, мы немедленно меняем поведение ситемы. Словом, отладчик своего рода «окно» в текущее состояние выполнения. Это как если бы вы могли изменить скрипт на веб-странице прямо в браузере — и изменения вступили в силу мгновенно, без перезагрузки.
А IDE в Smalltalk — не программа для написания кода. Это сама программа.
Необычно, правда?
Smalltalk — один из первых языков с полной рефлексией:
- Любой объект может сказать: «Кто мой класс?» (obj class)
- Любой класс может вернуть список своих методов (MyClass methods)
- Можно добавить метод в класс на лету:
String compile: 'reverseUppercase ^ self reversed asUppercase'
- Можно перехватить неизвестные сообщения:
doesNotUnderstand: aMessage
^ 'I don''t know ', aMessage selector
Многие практики современного программирования родились в этой экосистеме.
К примеру, рефакторинг - этот термин популяризирован Кентом Беком, который работал на Smalltalk. А также юнит-тестирование (SUnit), первый фреймворк для модульного тестирования, создан в Smalltalk (прообраз JUnit, NUnit). И конечно же экстремальное программирование, Extreme Programming (XP) — Кент Бек разработал его, используя Smalltalk и SUnit.
А теперь о минусах.
Как можно понять, есть обратная сторона, связанная с теми же особенностями. Например, проблемы безопасности. Полная рефлексия и возможность модификации системы на лету — риск, ведь любой код может изменить любой класс, а вредоносный скрипт может переписать что угодно. Это делает Smalltalk непригодным для систем с высокими требованиями к безопасности. Собственно современные языки в первую очередь потому и «живы» - из-за своей безопасности.
Далее - производительность. Интерпретируемый байт-код, паузы при автоматической сборке мусора, большое количество объектов - на практике всё это не подходит для высоконагруженных систем.
И конечно, дизайн. Отсутствие жёсткой структуры приводит к хаосу, и легко создавать магию (внезапно появляющиеся методы, перехват сообщений), и без дисциплины вся система станет непредсказуемой. Через неделю даже сам программист может не разобраться в своём же коде. Всё это не делает язык идеальным. Скорее полезным с точки зрения идеи и философии, учить думать иначе.
Можно встретить такие выражения, как «пуристская теория», которая как раз и подразумевает модель мышления, в которой программированием является не управлеине процессором, а организация диалога между объектами. Вы создаёте среду, в которой объекты общаются. Вы не вызываете функции — вы посылаете сообщения.
И суть в том, что мир состоит из изолированных сущностей (объектов), между которыми есть один единственный способ взаимодействия - посылка сообщений. И поведение делегируется, объект сам решает, как ответить. В реальной жизни всё так же - вы не управляете человеком, вы просите его что-то сделать, он может сказать «да», «нет», проигнорировать или ответить как-то ещё, вы не лезете внутрь его головы и не переписываете его мышление. Это и есть чистое ООП. И сообщение не будет гарантировать, что объект его поймёт, выполнит его так, как вы ожидаете, и он вообще ответит. Можно встретить забавный пример, если написать:
bird fly
Если bird - это Sparrow (попугай), то полетит. Если Penguin (пингвин), он получит сообщение, но ответит иначе:
fly
self inform: 'I can''t fly!'
Если bird — это Rock, он получит doesNotUnderstand: #fly — и можно перехватить.
Смысл уловили? Сообщение — это предложение.
В итоге у нас нет жёсткой связи между отправителем и получателем, и вы не знаете как ответит объект, что делает его изолированным субъектом со своим внутренним состоянием, реакцией.
Такие дела. Поэтому не ругайтесь с пуристами и не убеждайте, что какой-то язык настоящее ООП, кроме ST.
См. также
Другие статьи этого же раздела в боковом меню (как на странице «О разделе»). Мы с вами изучили основы кода, и особенно важным было изучение ООП - объектно-ориентированного программирования. И когда речь идёт об ООП, мы должны поговорить о Smalltalk - это самый правильный язык… Набор советов, правил, принципов и обычаев в разработке на этом языке. Гайд по установке и настройке с написанием первой программы и её запуском. В Smalltalk документация — это живые примеры в браузере классов. В индустрии — это Confluence-страницы и OpenAPI-спецификации. Особенности конструкций Smalltalk.Набор основных и важных ключевых слов в этом языке. Типизация, набор правил определения типа данных значений языка. Здесь — Object — родительский класс, Person — имя нового класса, name age — экземплярные переменные (приватные), package — MyApp — пространство имён Порядок вычисления определяется строго — Унарные сообщения (слева направо), Бинарные сообщения (слева направо), Ключевые сообщения (слева направо) Smalltalk — это чисто объектно-ориентированный язык программирования, созданный в 1970-х годах в исследовательском центре Xerox PARC. Он стал одной из первых сред, где всё без исключения является… Итоги и вопросы по теме Чек-лист самопроверки для самопроверки в энциклопедии Вселенная IT.Smalltalk - язык объектно-ориентированного программирования
Рекомендации по разработке на Smalltalk
Первая программа на Smalltalk
История языка Smalltalk
Синтаксис и особенности языка
Типы данных и переменные в Smalltalk
Объектно-ориентированная модель Smalltalk
Справочник по Smalltalk
Итоги
Чек-лист самопроверки